# coding=utf-8

import datetime
import functools
from roxe_libs.baseApi import *
import logging
from roxe_libs.Global import Global
from roxe_libs import settings, ApiUtils
from roxe_libs.DBClient import Mysql
import os
import copy
import time
from RMN.RMNStatusCode import RmnCodEnum


class RMNApiClient:

    def __init__(self, host, env, api_key=None, sec_key=None, version="001", check_db=False, sql_cfg=None, node_rsa_key=None):
        self.host = host
        self.env = env
        self.api_key = api_key
        self.sec_key = sec_key
        self.version = version
        self.iso_date_time_format = "%Y-%m-%dT%H:%M:%S"
        self.iso_date_format = "%Y-%m-%d"
        self.node_rsa_key = "../RTS/rsa_private_key.pem"
        if node_rsa_key:
            self.node_rsa_key = node_rsa_key

        self.dir_path = os.path.dirname(os.path.abspath(__file__))
        # 获取全局的日志记录logger
        self.logger = logging.getLogger(Global.getValue(settings.logger_name))
        self.check_db = check_db
        if check_db:
            self.mysql = Mysql(sql_cfg["mysql_host"], sql_cfg["port"], sql_cfg["user"], sql_cfg["password"], sql_cfg["db"], True)
            self.mysql.connect_database()

        traceable = Global.getValue(settings.enable_trace)
        if traceable:
            for handle in self.logger.handlers:
                #logger.handlers------日志处理程序 这段代码意思是如果是往文件里写log，那就设置为debug级别
                if "filehand" in str(handle).lower():
                    handle.setLevel(logging.DEBUG)
                handle.setLevel(logging.DEBUG)
            # print(self.logger.handlers)

 




    # API函数


    # 功能函数


    # 校验函数

    @staticmethod
    def checkCodeAndMessage(res, code="0", msg="Success"):
        # 校验response的code、message
        if isinstance(code, RmnCodEnum):
            assert res["code"] == code.code, f"{res['code']} not equal {code.code}"
            assert res["message"] == code.msg, f"{res['message']} not equal {code.msg}"
            return
        assert res["code"] == code, f"{res['code']} not equal {code}"
        assert res["message"] == msg, f"{res['message']} not equal {msg}"

    def checkHeaderLengthLimit(self, headers, callback, callArgs: list, headerLoc=1):
        length_headers = ["version:3", "sndrRID:12", "sndrApiKey:64", "rcvrRID:12", "msgTp:16", "msgId:25", "msgRefID:25", "sysFlg:4"]
        for i, key in enumerate(length_headers):
            h, h_len = key.split(":")
            new_headers = copy.deepcopy(headers)
            new_headers[h] = ApiUtils.generateString(int(h_len) + 1)
            self.logger.warning(f"header中{h}长度超限")
            self.logger.info(f"headers: {new_headers}")
            callArgs[headerLoc] = new_headers
            func_res, req_msg = callback(*callArgs)
            # h = "msgId" if h == "msgID" else h
            self.checkCodeAndMessage(func_res, "00100106", f"HTTP Header exception, {h} is not valid")

    def checkHeadersMissingField(self, headers, callback, callArgs: list):
        miss_headers = ["version", "sndrRID", "msgTp", "msgId", "sign"]
        for m_h in miss_headers:
            new_headers = headers.copy()
            callArgs[1] = new_headers
            tx_info, tx_msg = callback(*callArgs, popHeader=m_h)
            # m_h = "msgId" if m_h == "msgID" else m_h
            err_message = f"Missing request header '{m_h}' for method parameter of type String"
            self.checkCodeAndMessage(tx_info, "00100106", err_message)

    def checkEncryptBodyMissingField(self, callback, callArgs: list):
        for m_k in ["algorithm", "ciphertext", "nonce"]:
            tx_info, tx_msg = callback(*callArgs, popBody=m_k)
            self.checkCodeAndMessage(tx_info, "00100108", f"Encrypted message exception, {m_k} is empty")
        tx_info, tx_msg = callback(*callArgs, popBody="associatedData")
        self.checkCodeAndMessage(tx_info, "00200001", "Signature error")

    def checkEncryptBodyReplaceBody(self, callback, callArgs: list):
        for m_k in ["ciphertext", "nonce", "associatedData"]:
            tx_info, tx_msg = callback(*callArgs, repBody=m_k)
            self.checkCodeAndMessage(tx_info, "00200001", "Signature error")
        tx_info, tx_msg = callback(*callArgs, repBody="algorithm")
        self.checkCodeAndMessage(tx_info, "00100108", f"Encrypted message exception, algorithm should be AES_256_GCM")

    def checkBodyFieldsLengthLimit(self, fieldsLimit, callback, callArgs: list, bodyLoc=3, pre="cdtTrfTxInf."):
        rep_body = copy.deepcopy(callArgs[bodyLoc])
        for f_limit in fieldsLimit:
            tmp_body = copy.deepcopy(rep_body)
            field_key, field_len = f_limit.split(":")
            g_v = ApiUtils.generateString(int(field_len) + 1)
            tmp_d = ApiUtils.generateDict(field_key, g_v)
            tmp_body = ApiUtils.deepUpdateDict(tmp_body, tmp_d)
            callArgs[bodyLoc] = tmp_body
            tx_info, tx_msg = callback(*callArgs)
            self.checkCodeAndMessage(tx_info, "00100000", f"Parameter exception, {pre}{field_key} has invalid value:{g_v}")

    def checkBodyFieldsMissing(self, fieldsLimit, callback, callArgs: list, bodyLoc=3, pre="cdtTrfTxInf."):
        rep_body = copy.deepcopy(callArgs[bodyLoc])
        for field_key in fieldsLimit:
            tmp_body = copy.deepcopy(rep_body)
            tmp_d = ApiUtils.generateDict(field_key, None)
            tmp_body = ApiUtils.deepUpdateDict(tmp_body, tmp_d)
            callArgs[bodyLoc] = tmp_body
            tx_info, tx_msg = callback(*callArgs)
            self.checkCodeAndMessage(tx_info, "00100000", f"Parameter exception, {pre}{field_key} is empty")

    def getSttlMsgInfo(self, rmnTxnId, node, cdtDbtInd):
        body = {
            "rmnTxnId": rmnTxnId,
            "nodeCode": node,
            "cdtDbtInd": cdtDbtInd,
        }
        h = {"sndrApiKey": "aoe", "sndDtTm": "aoe", "sign": "aoe"}
        res = sendPostRequest(self.host + "/pcs/get-sttlMsg-info", json.dumps(body), h)
        self.logger.info(f"结果: {res.text}")





if __name__ == "__main__":
    logging.basicConfig()
    my_logger = logging.getLogger("rmn")
    my_logger.setLevel(logging.DEBUG)
    Global.setValue(settings.logger_name, my_logger.name)
    api = "XXXXXXXXXXXXXX"
    sec = "XXXXXXXXXXXXXXXXXXXXXXXX"
